package cn.xuan.zp.service.log.bo.impl;

import cn.xuan.zp.service.log.aop.LogAopAction;
import cn.xuan.zp.service.log.bo.IBusinessLogger;
import cn.xuan.zp.service.log.obj.LogInfo;
import cn.xuan.zp.service.log.utils.LoggerUtil;
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

@Service("business")
public class BusinessLoggerImpl implements IBusinessLogger {
    private static final Logger LOGGER = LoggerFactory.getLogger(BusinessLoggerImpl.class);
    /***
     * 方法前操作
     * @param joinPoint
     */
    @Override
    public void before(JoinPoint joinPoint) {
        LOGGER.info("BusinessLoggerImpl.before");
        try {
            readLog(joinPoint,null);
        } catch (ClassNotFoundException e) {
            LOGGER.error("BusinessLoggerImpl.before",e);
        }
    }

    /***
     * 方法后操作
     * @param joinPoint
     */
    @Override
    public void after(JoinPoint joinPoint) {
        LOGGER.info("BusinessLoggerImpl.after");
        try {
            readLog(joinPoint,null);
        } catch (ClassNotFoundException e) {
            LOGGER.error("BusinessLoggerImpl.after",e);
        }

    }

    /***
     * 返回参数接收
     * @param joinPoint
     * @param result
     */
    @Override
    public void afterReturn(JoinPoint joinPoint, Object result) {
        LOGGER.info("BusinessLoggerImpl.afterReturn");
        try {
            readLog(joinPoint,null);
        } catch (ClassNotFoundException e) {
            LOGGER.error("BusinessLoggerImpl.afterReturn",e);
        }

    }

    /***
     * 异常处理
     * @param joinPoint
     * @param ex
     */
    @Override
    public void throwing(JoinPoint joinPoint, Exception ex) {
        LOGGER.info("BusinessLoggerImpl.throwing");
        try {
            readLog(joinPoint,ex);
        } catch (ClassNotFoundException e) {
            LOGGER.error("BusinessLoggerImpl.throwing",e);
        }
    }

    void readLog(JoinPoint joinPoint, Exception ex) throws ClassNotFoundException {
        LogInfo log = new LogInfo();
        Map<String, String> map = LoggerUtil.getLogMark(joinPoint);

        log.setAction(map.get(LoggerUtil.LOG_ACTION));
        log.setTargetType(map.get(LoggerUtil.LOG_TARGET_TYPE));
        log.setRemark(map.get(LoggerUtil.LOG_REMARK));

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        SysUser user = (SysUser) request.getSession().getAttribute(SystemParams.AUTHEN_USER_PARAM_SYSTEM);

        String beanName = joinPoint.getSignature().getDeclaringTypeName();
        String methodName = joinPoint.getSignature().getName();
        String uri = request.getRequestURI();
        String remoteAddr = LoggerUtil.getIpAddr(request);
        String sessionId = request.getSession().getId();
        String method = request.getMethod();
        String params = "";


        //详细错误信息
        String errorMsg = "";
        String exMessage = null; // "异常方法名 " + ex.getMessage() + "\r\n" + errorMsg;
        if(ex != null){
            StackTraceElement[] trace = ex.getStackTrace();
            for (StackTraceElement s : trace) {
                errorMsg += "\tat " + s + "\r\n";
            }
            exMessage = "异常方法名 " + ex.getMessage() + "\r\n" + errorMsg;
        }
//            String exMessage = "异常方法名 " + ex.getMessage() + "\r\n" + errorMsg;
        if ("POST".equals(method)) {
            Object[] paramsArray = joinPoint.getArgs();
            params = LoggerUtil.argsArrayToString(paramsArray);//Arrays.toString(paramsArray);
        } else {
            Map<?, ?> paramsMap = (Map<?, ?>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            params = paramsMap.toString();
        }

        log.setBeanName(beanName);
        log.setMethodName(methodName);
        log.setParams(params != null ? params.toString() : "");
        log.setRemoteAddr(remoteAddr);
        log.setSessionId(sessionId);
        log.setUri(uri);
        log.setBeginTime(new Date());
        log.setRemoteAddr(LoggerUtil.getCliectIp(request));

        log.setExMessage(exMessage);

        LOGGER.info(log.toString());

    }
}
